package admin

import (
	"encoding/csv"
	"fmt"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"myai/core"
	"myai/core/types"
	"myai/handler"
	"myai/store/model"
	"myai/store/model/req"
	"myai/store/vo"
	"myai/utils"
	"myai/utils/resp"
)

type RedeemHandler struct {
	handler.BaseHandler
}

func NewRedeemHandler(app *core.AppServer, db *gorm.DB) *RedeemHandler {
	return &RedeemHandler{BaseHandler: handler.BaseHandler{App: app, DB: db}}
}

// List godoc
// @Summary      查询列表
// @Description  查询列表
// @Tags         后台管理-兑换码管理
// @Accept       json
// @Produce      json
// @Param        page   	 query     int     true  "页码"
// @Param        page_size   query     int     true  "每页数量"
// @Param        code   	 query     string  false  "兑换码"
// @Param        status   	 query     int     false  "状态"
// @Success      200  {object}  types.BizVo{data=vo.Page}
// @Router       /api/admin/redeem/list [get]
// @Security AdminApiKeyAuth
func (h *RedeemHandler) List(c *gin.Context) {
	page := h.GetInt(c, "page", 1)
	pageSize := h.GetInt(c, "page_size", 20)
	code := h.GetTrim(c, "code")
	status := h.GetInt(c, "status", -1)

	session := h.DB.Session(&gorm.Session{})
	if code != "" {
		session = session.Where("code like ?", fmt.Sprintf("%s%s%s", "%", code, "%"))
	}
	if status == 0 {
		session = session.Where("redeemed_at", status)
	} else if status > 0 {
		session = session.Where("redeemed_at > ?", status)
	}

	var total int64
	// 查询兑换码数量
	session.Model(&model.Redeem{}).Count(&total)
	var redeems []model.Redeem
	offset := (page - 1) * pageSize
	err := session.Order("id desc").Offset(offset).Limit(pageSize).Find(&redeems).Error
	if err != nil {
		resp.ERROR(c, "操作数据库失败："+err.Error())
		return
	}

	var items = make([]vo.Redeem, 0)
	userIds := make([]uint, 0)
	for _, v := range redeems {
		userIds = append(userIds, v.UserId)
	}

	var users []model.User
	// 查询用户信息
	h.DB.Where("id IN ?", userIds).Find(&users)

	var userMap = make(map[uint]model.User)
	for _, user := range users {
		userMap[user.Id] = user
	}

	for _, v := range redeems {
		var r vo.Redeem
		err = utils.CopyObject(v, &r)
		if err != nil {
			log.Errorf("拷贝数据出错：%v", err.Error())
			continue
		}
		r.Id = v.Id
		r.Username = userMap[v.UserId].Username
		r.CreatedAt = v.CreatedAt.Unix()
		items = append(items, r)
	}
	resp.SUCCESS(c, vo.NewPage(total, page, pageSize, items))
}

// Export godoc
// @Summary      导出文件
// @Description  导出文件
// @Tags         后台管理-兑换码管理
// @Accept       json
// @Produce      application/octet-stream
// @Param        req   	 body   req.RedeemExportReq     true  "导出条件信息"
// @Success 	 200 {file} file "文件内容"
// @Header 		 200 {string} Content-Disposition "attachment; filename=output.csv"
// @Router       /api/admin/redeem/export [post]
// @Security AdminApiKeyAuth
func (h *RedeemHandler) Export(c *gin.Context) {
	var data req.RedeemExportReq
	if err := c.ShouldBindJSON(&data); err != nil {
		resp.ERROR(c, types.InvalidArgs)
		return
	}

	session := h.DB.Session(&gorm.Session{})
	if data.Status >= 0 {
		session = session.Where("redeemed_at", data.Status)
	}
	if len(data.Ids) > 0 {
		session = session.Where("id IN ?", data.Ids)
	}
	var items []model.Redeem
	err := session.Order("id desc").Find(&items).Error
	if err != nil {
		resp.ERROR(c, "操作数据库失败："+err.Error())
		return
	}
	// 设置响应头，告诉浏览器这是一个附件，需要下载
	c.Header("Content-Disposition", "attachment; filename=output.csv")
	c.Header("Content-Type", "text/csv")

	// 创建一个 CSV Writer
	writer := csv.NewWriter(c.Writer)
	// 写 CSV 文件的标题行
	headers := []string{"名称", "兑换码", "算力", "创建时间"}
	if err := writer.Write(headers); err != nil {
		resp.ERROR(c, "写入 CSV 标题行出错："+err.Error())
		return
	}
	// 写入数据行
	records := make([][]string, 0)
	// 组装数据行
	for _, item := range items {
		records = append(records, []string{item.Name, item.Code, fmt.Sprintf("%d", item.Power), item.CreatedAt.Format("2006-01-02 15:04:05")})
	}
	for _, record := range records {
		// 写入数据
		if err := writer.Write(record); err != nil {
			resp.ERROR(c, "写入数据时失败："+err.Error())
			return
		}
	}
	// 确保所有数据都已写入响应
	writer.Flush()
	if err := writer.Error(); err != nil {
		resp.ERROR(c, "写入数据时出错："+err.Error())
	}
}

// Create godoc
// @Summary      添加兑换码
// @Description  添加兑换码
// @Tags         后台管理-兑换码管理
// @Accept       json
// @Produce      json
// @Param        req   	 body   req.RedeemSaveReq     true  "兑换码信息"
// @Success      200  {object}  types.BizVo{}
// @Router       /api/admin/redeem/create [post]
// @Security AdminApiKeyAuth
func (h *RedeemHandler) Create(c *gin.Context) {
	var data req.RedeemSaveReq
	if err := c.ShouldBindJSON(&data); err != nil {
		resp.ERROR(c, types.InvalidArgs)
		return
	}
	// 添加数量
	counter := 0
	// 存储code码
	codes := make([]string, 0)
	var errMsg = ""
	if data.Num > 0 {
		for i := 0; i < data.Num; i++ {
			// 生成兑换码
			code, err := utils.GenRedeemCode(32)
			if err != nil {
				errMsg = err.Error()
				continue
			}
			// 添加兑换码
			err = h.DB.Create(&model.Redeem{
				Code:    code,
				Name:    data.Name,
				Power:   data.Power,
				Enabled: true,
			}).Error
			if err != nil {
				errMsg = err.Error()
				continue
			}
			codes = append(codes, code)
			counter++
		}
	}
	if counter == 0 {
		resp.ERROR(c, errMsg)
		return
	}
	resp.SUCCESS(c, gin.H{"counter": counter})
}

// Set godoc
// @Summary      修改指定字段的值
// @Description  修改指定字段的值
// @Tags         后台管理-兑换码管理
// @Accept       json
// @Produce      json
// @Param        req   	 body   req.RedeemFiledUpdateReq     true  "要修改字段的值"
// @Success      200  {object}  types.BizVo{}
// @Router       /api/admin/redeem/set [post]
// @Security AdminApiKeyAuth
func (h *RedeemHandler) Set(c *gin.Context) {
	var data req.RedeemFiledUpdateReq
	if err := c.ShouldBindJSON(&data); err != nil {
		resp.ERROR(c, types.InvalidArgs)
		return
	}
	err := h.DB.Model(&model.Redeem{}).Where("id", data.Id).Update(data.Filed, data.Value).Error
	if err != nil {
		resp.ERROR(c, "操作数据库失败："+err.Error())
		return
	}
	resp.SUCCESS(c)
}

// Remove godoc
// @Summary      根据Id删除兑换码
// @Description  根据Id删除兑换码
// @Tags         后台管理-兑换码管理
// @Accept       json
// @Produce      json
// @Param        id   	 query     int     true  "兑换码Id"
// @Success      200  {object}  types.BizVo{}
// @Router       /api/admin/redeem/remove [get]
// @Security AdminApiKeyAuth
func (h *RedeemHandler) Remove(c *gin.Context) {
	id := h.GetInt(c, "id", 0)
	if id <= 0 {
		resp.ERROR(c, types.InvalidArgs)
		return
	}
	err := h.DB.Where("id", id).Delete(&model.Redeem{}).Error
	if err != nil {
		resp.ERROR(c, "操作数据库出错："+err.Error())
		return
	}
	resp.SUCCESS(c)
}
